import { IRecoverable } from "../../base/pool/IRecoverable";
import { Task } from "./Task";

/**
 * 任务序列（并行）
 */
export class TaskQueue extends Task implements IRecoverable {

    private _taskMap: Map<Task, any[]> = new Map();
    private _index: number = 0;
    constructor() {
        super();
    }
    
    addQuickly(taskCaller:any, taskFun:(task:Task, ...taskData)=>void, ...taskData): Task {
        let task:Task = new Task();
        taskData.unshift(task);
        task.start = (data?: any)=>{
            taskFun.apply(taskCaller, taskData);
        }
        this.addTask(task);
        return task;
    }

    addTask(value: Task, ...data:any[]): void {
        if (this._taskMap.has(value)) {
            throw new Error("重复添加！");
        }
        this._taskMap.set(value, data);
    }

    removeTask(value: Task): boolean {
        return this._taskMap.delete(value);
    }

    start(...data: any): void {
        this._taskMap.forEach((data:any[], task:Task)=>{
            task.on(Task.Event.COMPLETE, this, this._subTaskEventHandler);
            task.on(Task.Event.ERROR, this, this._subTaskEventHandler);
            task.on(Task.Event.PROGRESS, this, this._subTaskEventHandler);
            task.start(...data);
        })
    }

    private _subTaskEventHandler(type: string, target: Task, data?: any): void {
        if (type == Task.Event.ERROR) {
            this.onError(data.code, data.msg);
            return;
        }
        if(type == Task.Event.COMPLETE){
            target.destroy();
            this._index++;
            this.onProgress(this._index / this._taskMap.size);
            if (this._index >= this._taskMap.size) {
                //完成
                this.onComplete();
            }
        }
    }

    reset(): void {
        this.offAllEvent();
        this._taskMap.forEach((data, task:Task)=>{
            task.reset();
        })
        this._taskMap.clear();
        this._index = 0;
    }

    destroy(): void {
        super.destroy();
        this._taskMap.forEach((data, task:Task)=>{
            task.reset();
        })
        this._taskMap.clear();
        this._index = 0;
    }
}
